package com.zb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zb.entity.*;
import com.zb.exception.ZbException;
import com.zb.mapper.ZjRoleMapper;
import com.zb.result.PageUtil;
import com.zb.service.ZjAccountRoleService;
import com.zb.service.ZjCustomerAuthorService;
import com.zb.service.ZjRoleAuthorService;
import com.zb.service.ZjRoleService;
import com.zb.vo.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author WEN
 * @since 2023-07-18
 */
@Service
public class ZjRoleServiceImpl extends ServiceImpl<ZjRoleMapper, ZjRole> implements ZjRoleService {
    @Resource
    private ZjRoleMapper roleMapper;
    @Resource
    private ZjRoleAuthorService roleAuthorService;
    @Resource
    private ZjAccountRoleService accountRoleService;
    @Resource
    private ZjCustomerAuthorService customerAuthorService;

    // 新增系统超管角色
    @Override
    public void saveAdminRole(Long custAccId, Long accountId) {
        ZjRole role = new ZjRole();
        role.setId(IdWorker.getId());
        role.setCustAccId(custAccId);
        role.setName("系统超管");
        role.setCode("admin_boss");
        role.setAdmin(true);
        role.setDisabled(false);
        this.save(role);
        accountRoleService.saveAdminAccountRole(custAccId, accountId, role.getId());
        saveDefaultRole(custAccId);
    }

    // 新增或修改角色权限
    @Override
    @Transactional
    public void save(Long custAccId, RoleVo roleVo) throws ZbException {
        Assert.isTrue(null == roleMapper.existByName(custAccId, roleVo.getId(), roleVo.getName()), "角色名称不能重复", roleVo.getName());
        Assert.isTrue(null == roleMapper.existByCode(custAccId, roleVo.getId(), roleVo.getCode()), "角色编码不能重复", roleVo.getCode());
        ZjRole role = new ZjRole();
        role.setName(roleVo.getName());
        role.setCode(roleVo.getCode());
        role.setDisabled(roleVo.getStatus());
        if (null != roleVo.getId()) {
            Assert.isTrue(null == roleMapper.existAdminById(roleVo.getId()), "该角色为系统超管，不可更改或删除", null);
            role.setId(roleVo.getId());
            this.updateById(role);
        } else {
            role.setId(IdWorker.getId());
            role.setCustAccId(custAccId);
            role.setAdmin(false);
            this.save(role);
        }
//        accountRoleService.save(custAccId, roleVo.getEmpIds(), role.getId());
//        roleAuthorService.save(custAccId, role.getId(), roleVo.getAuthorIds());
    }

    // 创建保存默认角色
    @Override
    public void saveDefaultRole(Long custAccId) {
        ZjRole role = new ZjRole();
        role.setId(IdWorker.getId());
        role.setCustAccId(custAccId);
        role.setName("普通管理员");
        role.setCode("zb_manager");
        role.setAdmin(false);
        role.setDisabled(false);
        this.save(role);
    }

    @Override
    public Map<String, Object> getList(RoleSelectVo roleSelectVo) {
        QueryWrapper<ZjRole> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("is_admin", "gmt_update");
        wrapper.eq("cust_acc_id", roleSelectVo.getCustAccId());
        if (StringUtils.isNotBlank(roleSelectVo.getKeyword())) {
            wrapper.like("name", roleSelectVo.getKeyword());
            wrapper.or();
            wrapper.like("code", roleSelectVo.getKeyword());
        }
        PageUtil.setPageLimit(roleSelectVo);
        Page<ZjRole> page = this.page(new Page<>(roleSelectVo.getPage(), roleSelectVo.getLimit()), wrapper);

        List<RolesVo> voList = new ArrayList<>();
        page.getRecords().forEach(t -> voList.add(RolesVo.beanToVo(t)));
        return PageUtil.pageList(page.getCurrent(), page.getSize(), page.getTotal(), voList);
    }

    // 批量启用或禁用角色状态
    @Override
    public void updateDisableBatchByIds(List<Long> idList, boolean disable) {
        existAdminByIds(idList);
        roleMapper.updateDisableBatchByIds(idList, disable);
    }

    // 根据角色ID集合查询角色ID集合中是否存在系统超管
    @Override
    public void existAdminByIds(List<Long> idList) {
        Assert.isTrue(null == roleMapper.existAdminByIds(idList), "操作的角色包含有系统超管，不可操作！", null);
    }

    // 根据[账号ID]&[商家ID]集合查询角色
    @Override
    public List<ZjRole> getByAccountIdAndCustAccIds(Long accountId, List<Long> custAccIds) {
        return roleMapper.getByAccountIdAndCustAccIds(accountId, custAccIds);
    }

    // 企业角色下拉数据列表
    @Override
    public Map<String, Object> pageSelecct(Long custAccId, SelectVo selectVo) {
        QueryWrapper<ZjRole> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name");
        wrapper.eq("cust_acc_id", custAccId);
        wrapper.eq("is_admin", false);
        wrapper.eq("is_disabled", false);
        if (StringUtils.isNotBlank(selectVo.getName())) {
            wrapper.like("name", selectVo.getName());
        }
        PageUtil.setSelectPageLimit(selectVo);
        Page<ZjRole> page = this.page(new Page<>(selectVo.getPage(), selectVo.getLimit()), wrapper);
        List<SelectResultVo> voList = new ArrayList<>();
        page.getRecords().forEach(t -> voList.add(new SelectResultVo(t.getId(), t.getName())));
        return PageUtil.pageList(page.getCurrent(), page.getSize(), page.getTotal(), voList);
    }

    // 保存角色权限
    @Override
    @Transactional
    public void saveRoleAuthor(Long custAccId, Long id, List<RoleAuthorVo> roleAuthorVos) {
        ZjRole role = this.getById(id);
        Assert.isFalse(role.getAdmin(), "该角色为系统超管，禁止修改权限");
        roleAuthorService.save(custAccId, id, roleAuthorVos);
    }

    // 根据角色ID获取角色权限
    @Override
    public List<RoleAuthorVo> getRoleAuthor(Long custAccId, Long id) {
        ZjRole role = this.getById(id);
        List<ZjRoleAuthor> authorList = new ArrayList<>();
        if (role.getAdmin()) {
            authorList.addAll(roleAuthorService.getAdminAuthorByCustAccId(custAccId));
        } else {
            authorList.addAll(roleAuthorService.getRoleAuthorByRoleId(id));
        }
        return authorList.stream().filter(f -> f.getParentAuthorId() == 0).map(author -> {
            RoleAuthorVo vo = new RoleAuthorVo();
            vo.setAuthorId(author.getAuthorId());
            vo.setAuthorVos(getChildAuthor(vo.getAuthorId(), authorList));
            return vo;
        }).toList();
    }

    private List<RoleAuthorVo> getChildAuthor(Long parentAuthorId, List<ZjRoleAuthor> authorList) {
        return authorList.stream().filter(f -> Objects.equals(f.getParentAuthorId(), parentAuthorId)).map(author -> {
            RoleAuthorVo vo = new RoleAuthorVo();
            vo.setAuthorId(author.getAuthorId());
            vo.setAuthorVos(getChildAuthor(vo.getAuthorId(), authorList));
            return vo;
        }).toList();
    }

    // 根据账号获取菜单权限
    @Override
    public List<MenuAuthorVo> getAuthors(AccounLoginInfo loginInfo) {
        Long roleId = accountRoleService.getRoleIdByAccountId(loginInfo.getCustAccId(), loginInfo.getId());
        ZjRole role = this.getById(roleId);
        List<AuthorVo> voList = new ArrayList<>();
        if (role.getAdmin()) {
            voList.addAll(customerAuthorService.getAdminRootByCustAccId(loginInfo.getCustAccId()));
        } else {
            voList.addAll(roleAuthorService.getAuthorByCustAccIdAndRoleId(loginInfo.getCustAccId(), roleId));
        }
        return voList.stream().filter(f -> f.getParentId() == 0).map(author -> {
            MenuAuthorVo vo = new MenuAuthorVo();
            BeanUtil.copyProperties(author, vo);
            vo.setMeta(new MenuAuthorMetaVo(author.getTitle(), author.getIcon(), author.getKeepAlive()));
            vo.setAuthorVos(getAuthorData(author.getAuthorId(), voList));
            return vo;
        }).toList();
    }

    private List<MenuAuthorVo> getAuthorData(Long parentId, List<AuthorVo> voList) {
        return voList.stream().filter(f -> Objects.equals(f.getParentId(), parentId)).map(author -> {
            MenuAuthorVo vo = new MenuAuthorVo();
            BeanUtil.copyProperties(author, vo);
            vo.setMeta(new MenuAuthorMetaVo(author.getTitle(), author.getIcon(), author.getKeepAlive()));
            vo.setAuthorVos(getAuthorData(author.getAuthorId(), voList));
            return vo;
        }).toList();
    }
}
